/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.wui.client.common.utils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.roda.wui.client.browse.MetadataValue;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONException;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.datepicker.client.DateBox;
import config.i18n.client.ClientMessages;
/**
* Created by adrapereira on 13-06-2016.
*/
public class FormUtilities {
private FormUtilities() {
}
private static final ClientMessages messages = GWT.create(ClientMessages.class);
public static void create(FlowPanel panel, Set<MetadataValue> bundle, boolean addStyle) {
for (MetadataValue mv : bundle) {
boolean mandatory = (mv.get("mandatory") != null && "true".equalsIgnoreCase(mv.get("mandatory"))) ? true : false;
if (mv.get("hidden") != null && "true".equals(mv.get("hidden")))
continue;
FlowPanel layout = new FlowPanel();
if (addStyle) {
layout.addStyleName("metadata-form-field");
}
String controlType = mv.get("type");
if (controlType == null) {
addTextField(panel, layout, mv, mandatory);
} else {
switch (controlType) {
case "text":
addTextField(panel, layout, mv, mandatory);
break;
case "textarea":
case "big-text":
case "text-area":
addTextArea(panel, layout, mv, mandatory);
break;
case "list":
addList(panel, layout, mv, mandatory);
break;
case "date":
addDatePicker(panel, layout, mv, mandatory);
break;
case "separator":
layout.addStyleName("form-separator");
addSeparator(panel, layout, mv);
break;
default:
addTextField(panel, layout, mv, mandatory);
break;
}
}
}
}
private static String getFieldLabel(MetadataValue mv) {
String result = mv.getId();
String rawLabel = mv.get("label");
if (rawLabel != null && rawLabel.length() > 0) {
String loc = LocaleInfo.getCurrentLocale().getLocaleName();
try {
JSONObject jsonObject = JSONParser.parseLenient(rawLabel).isObject();
JSONValue jsonValue = jsonObject.get(loc);
if (jsonValue != null) {
JSONString jsonString = jsonValue.isString();
if (jsonString != null) {
result = jsonString.stringValue();
}
} else {
if (loc.contains("_")) {
jsonValue = jsonObject.get(loc.split("_")[0]);
if (jsonValue != null) {
JSONString jsonString = jsonValue.isString();
if (jsonString != null) {
result = jsonString.stringValue();
}
}
}
// label for the desired language doesn't exist
// do nothing
}
} catch (JSONException e) {
// The JSON was malformed
// do nothing
}
}
mv.set("l", result);
return result;
}
private static void addTextField(FlowPanel panel, final FlowPanel layout, final MetadataValue mv,
final boolean mandatory) {
// Top label
Label mvLabel = new Label(getFieldLabel(mv));
mvLabel.addStyleName("form-label");
if (mandatory) {
mvLabel.addStyleName("form-label-mandatory");
}
// Field
final TextBox mvText = new TextBox();
mvText.setTitle(mvLabel.getText());
mvText.addStyleName("form-textbox");
if (mv.get("value") != null) {
mvText.setText(mv.get("value"));
}
mvText.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent changeEvent) {
mv.set("value", mvText.getValue());
if (mandatory && (mvText.getValue() != null && !"".equalsIgnoreCase(mvText.getValue().trim()))) {
mvText.removeStyleName("isWrong");
} else if (mandatory && (mvText.getValue() == null || "".equals(mvText.getValue().trim()))) {
mvText.addStyleName("isWrong");
}
}
});
layout.add(mvLabel);
layout.add(mvText);
// Description
String description = mv.get("description");
if (description != null && description.length() > 0) {
Label mvDescription = new Label(description);
mvDescription.addStyleName("form-help");
layout.add(mvDescription);
}
if (mv.get("error") != null && !"".equals(mv.get("error").trim())) {
Label errorLabel = new Label(mv.get("error"));
errorLabel.addStyleName("form-label-error");
layout.add(errorLabel);
mvText.addStyleName("isWrong");
}
panel.add(layout);
}
private static void addTextArea(FlowPanel panel, final FlowPanel layout, final MetadataValue mv,
final boolean mandatory) {
// Top label
Label mvLabel = new Label(getFieldLabel(mv));
mvLabel.addStyleName("form-label");
if (mandatory) {
mvLabel.addStyleName("form-label-mandatory");
}
// Field
final TextArea mvText = new TextArea();
mvText.setTitle(mvLabel.getText());
mvText.addStyleName("form-textbox metadata-form-text-area");
if (mv.get("value") != null) {
mvText.setText(mv.get("value"));
}
mvText.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent changeEvent) {
mv.set("value", mvText.getValue());
if (mandatory && (mvText.getValue() != null && !"".equals(mvText.getValue().trim()))) {
mvText.removeStyleName("isWrong");
} else if (mandatory && (mvText.getValue() == null || "".equalsIgnoreCase(mvText.getValue().trim()))) {
mvText.addStyleName("isWrong");
}
}
});
layout.add(mvLabel);
layout.add(mvText);
// Description
String description = mv.get("description");
if (description != null && description.length() > 0) {
Label mvDescription = new Label(description);
mvDescription.addStyleName("form-help");
layout.add(mvDescription);
}
if (mv.get("error") != null && !"".equalsIgnoreCase(mv.get("error").trim())) {
Label errorLabel = new Label(mv.get("error"));
errorLabel.addStyleName("form-label-error");
layout.add(errorLabel);
mvText.addStyleName("isWrong");
}
panel.add(layout);
}
private static void addList(FlowPanel panel, final FlowPanel layout, final MetadataValue mv,
final boolean mandatory) {
// Top Label
Label mvLabel = new Label(getFieldLabel(mv));
mvLabel.addStyleName("form-label");
if (mandatory) {
mvLabel.addStyleName("form-label-mandatory");
}
// Field
final ListBox mvList = new ListBox();
mvList.setTitle(mvLabel.getText());
mvList.addStyleName("form-textbox");
String options = mv.get("options");
JSONArray optionsArray = null;
if (options != null) {
optionsArray = JSONParser.parseLenient(options).isArray();
}
String list = mv.get("optionsLabels");
mvList.addItem("");
if (list != null) {
JSONArray jsonArray = JSONParser.parseLenient(list).isArray();
if (jsonArray != null) {
for (int i = 0; i < jsonArray.size(); i++) {
String value = jsonArray.get(i).isString().stringValue();
mvList.addItem(value);
if (value.equals(mv.get("value"))) {
mvList.setSelectedIndex(i + 1);
}
}
} else {
JSONObject jsonObject = JSONParser.parseLenient(list).isObject();
if (jsonObject != null) {
String loc = LocaleInfo.getCurrentLocale().getLocaleName();
int i = 0;
if (optionsArray != null) {
for (int pos = 0; pos < optionsArray.size(); pos++) {
String key = optionsArray.get(pos).isString().stringValue();
JSONValue entry = jsonObject.get(key);
if (entry.isObject() != null) {
JSONValue jsonValue = entry.isObject().get(loc);
String value;
if (jsonValue != null) {
value = jsonValue.isString().stringValue();
} else {
value = entry.isObject().get(entry.isObject().keySet().iterator().next()).isString().stringValue();
}
if (value != null) {
mvList.addItem(value, key);
if (key.equals(mv.get("value"))) {
mvList.setSelectedIndex(i + 1);
}
}
}
i++;
}
} else {
for (String key : jsonObject.keySet()) {
JSONValue entry = jsonObject.get(key);
if (entry.isObject() != null) {
JSONValue jsonValue = entry.isObject().get(loc);
String value;
if (jsonValue != null) {
value = jsonValue.isString().stringValue();
} else {
value = entry.isObject().get(entry.isObject().keySet().iterator().next()).isString().stringValue();
}
if (value != null) {
mvList.addItem(value, key);
if (key.equals(mv.get("value"))) {
mvList.setSelectedIndex(i + 1);
}
}
}
i++;
}
}
}
}
} else {
if (optionsArray != null) {
int i = 0;
for (int pos = 0; pos < optionsArray.size(); pos++) {
String key = optionsArray.get(pos).isString().stringValue();
if (key != null) {
mvList.addItem(key, key);
if (key.equals(mv.get("value"))) {
mvList.setSelectedIndex(i + 1);
}
}
i++;
}
}
}
mvList.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent changeEvent) {
mv.set("value", mvList.getSelectedValue());
if (mandatory && (mvList.getSelectedValue() != null && !"".equals(mvList.getSelectedValue().trim()))) {
mvList.removeStyleName("isWrong");
}
if (mandatory && (mvList.getSelectedValue() == null || "".equalsIgnoreCase(mvList.getSelectedValue().trim()))) {
mvList.removeStyleName("isWrong");
}
}
});
if (mv.get("value") == null || mv.get("value").isEmpty()) {
mvList.setSelectedIndex(0);
mv.set("value", mvList.getSelectedValue());
}
layout.add(mvLabel);
layout.add(mvList);
// Description
String description = mv.get("description");
if (description != null && description.length() > 0) {
Label mvDescription = new Label(description);
mvDescription.addStyleName("form-help");
layout.add(mvDescription);
}
if (mv.get("error") != null && !"".equals(mv.get("error").trim())) {
Label errorLabel = new Label(mv.get("error"));
errorLabel.addStyleName("form-label-error");
layout.add(errorLabel);
mvList.addStyleName("isWrong");
}
panel.add(layout);
}
private static void addDatePicker(FlowPanel panel, final FlowPanel layout, final MetadataValue mv,
final boolean mandatory) {
// Top label
final DateTimeFormat dateTimeFormat = DateTimeFormat.getFormat("yyyy-MM-dd");
Label mvLabel = new Label(getFieldLabel(mv));
mvLabel.addStyleName("form-label");
if (mandatory) {
mvLabel.addStyleName("form-label-mandatory");
}
// Field
final DateBox mvDate = new DateBox();
mvDate.setTitle(mvLabel.getText());
mvDate.getDatePicker().setYearAndMonthDropdownVisible(true);
mvDate.getDatePicker().setYearArrowsVisible(true);
mvDate.addStyleName("form-textbox");
mvDate.setFormat(new DateBox.DefaultFormat() {
@Override
public String format(DateBox dateBox, Date date) {
if (date == null)
return null;
return dateTimeFormat.format(date);
}
});
String value = mv.get("value");
if (value != null && value.length() > 0) {
try {
Date date = dateTimeFormat.parse(value.trim());
mvDate.setValue(date);
} catch (IllegalArgumentException iae) {
mvDate.getTextBox().setValue(value);
}
}
mvDate.addValueChangeHandler(new ValueChangeHandler<Date>() {
@Override
public void onValueChange(ValueChangeEvent<Date> valueChangeEvent) {
String newValue = dateTimeFormat.format(mvDate.getValue());
mv.set("value", newValue);
if (mandatory && (newValue != null && !"".equals(newValue.trim()))) {
mvDate.removeStyleName("isWrong");
} else if (mandatory && (newValue == null || "".equals(newValue.trim()))) {
mvDate.addStyleName("isWrong");
}
}
});
mvDate.getTextBox().addValueChangeHandler(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
String value = event.getValue();
try {
Date date = dateTimeFormat.parse(value.trim());
mvDate.setValue(date);
mv.set("value", value);
} catch (IllegalArgumentException iae) {
if (event.getValue() == null || "".equals(event.getValue().trim())) {
mv.set("value", null);
}
mvDate.getTextBox().setValue(value);
}
}
});
layout.add(mvLabel);
layout.add(mvDate);
// Description
String description = mv.get("description");
if (description != null && description.length() > 0) {
Label mvDescription = new Label(description);
mvDescription.addStyleName("form-help");
layout.add(mvDescription);
}
if (mv.get("error") != null && !"".equals(mv.get("error").trim())) {
Label errorLabel = new Label(mv.get("error"));
errorLabel.addStyleName("form-label-error");
layout.add(errorLabel);
mvDate.addStyleName("isWrong");
}
panel.add(layout);
}
private static void addSeparator(FlowPanel panel, final FlowPanel layout, final MetadataValue mv) {
Label mvLabel = new Label(getFieldLabel(mv));
layout.add(mvLabel);
// Description
String description = mv.get("description");
if (description != null && description.length() > 0) {
Label mvDescription = new Label(description);
mvDescription.addStyleName("form-help");
layout.add(mvDescription);
}
panel.add(layout);
}
public static List<String> validate(Set<MetadataValue> values, FlowPanel extra) {
List<String> errors = new ArrayList<>();
if (values != null) {
for (MetadataValue mv : values) {
String value = mv.get("value");
boolean mandatory = (mv.get("mandatory") != null && "true".equalsIgnoreCase(mv.get("mandatory"))) ? true
: false;
if (mandatory && (value == null || "".equals(value.trim()))) {
String labels = mv.get("l");
errors.add(messages.isAMandatoryField(labels));
mv.set("error", messages.mandatoryField());
} else {
mv.set("error", null);
}
}
}
extra.clear();
create(extra, values, true);
return errors;
}
}